﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using System.Windows.Forms;

namespace DownloadBook {
    public partial class FrmMergeContent : Form {
        private readonly Book m_Book;
        private Regex m_Regex;
        private int m_GroupId;
        private Regex m_RegRemove;

        private MergeConfig m_MergeConfig;
        private readonly FrmMain m_FrmMain;
        private readonly MergeConfigServer m_MergeConfigService;


        private string m_OutputFilePath;
        public string OutputFilePath {
            get {
                if (string.IsNullOrEmpty(m_OutputFilePath)) {
                    string outFileName = string.Format("{0}.txt", m_Book.name);
                    string outDirectory = Path.Combine(Environment.CurrentDirectory, "txt");
                    if (!Directory.Exists(outDirectory)) {
                        Directory.CreateDirectory(outDirectory);
                    }
                    m_OutputFilePath = Path.Combine(outDirectory, outFileName);
                }
                return m_OutputFilePath;
            }
        }


        private FrmMergeContent() {
            InitializeComponent();
        }

        public FrmMergeContent(FrmMain frmMain, Book book) : this(){
            this.m_Book = book;
            this.m_FrmMain = frmMain;
            m_MergeConfigService = MergeConfigServer.instance;
        }

        private void FrmMergeContent_Load(object sender, EventArgs e) {
            //添加全选功能
            SelectAllSupport.Bind(txtAuthor);
            SelectAllSupport.Bind(txtExtractPreview);
            SelectAllSupport.Bind(txtIntroduction);
            SelectAllSupport.Bind(txtOriginHtml);
            SelectAllSupport.Bind(txtRegContent);
            SelectAllSupport.Bind(txtRegContentGroupId);
            SelectAllSupport.Bind(txtRegRemove);

            //载入配置
            LoadConfig();
            
            //显示章节列表
            if(this.m_Book.contentList.Count > 0){
                this.comContent.Items.AddRange(this.m_Book.contentList.ToArray());
                this.comContent.SelectedIndex = 0;
            }

            lblMsg.Text = "准备就绪";
        }


        private void FrmMergeContent_FormClosed(object sender, FormClosedEventArgs e) {
            this.m_FrmMain.SaveHistory();
        }

        /// <summary>
        /// 载入配置按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnLoadConfig_Click(object sender, EventArgs e) {
            LoadConfig();
        }
        /// <summary>
        /// 保存合并配置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TxtSaveConfig_Click(object sender, EventArgs e) {
            UpdateConfig();
        }

        /// <summary>
        /// 预览按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnExtractPreview_Click(object sender, EventArgs e) {
            ExtractPreview();
        }
        
        /// <summary>
        /// 合并按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnMergeTxt_Click(object sender, EventArgs e) {
            CreateMatch();
            UpdateConfig();

            string author = txtAuthor.Text;
            string introduction = txtIntroduction.Text;
            Thread thread = new Thread(() => {
                MerageText(author, introduction, (msg) => {
                    this.Invoke(new EventHandler(delegate {
                        lblMsg.Text = msg;
                    }));
                });
            }) {
                IsBackground = true
            };
            thread.Start();
        }

        /// <summary>
        /// 合并预览
        /// </summary>
        private void ExtractPreview() {
            LoadDefaultOriginHtml(); //载入默认的原始html
            CreateMatch();
            
            txtExtractPreview.Text = "准备中，请稍候！";
            
            ContentServer.ExtractContent(this.m_Regex, txtOriginHtml.Text, this.m_GroupId, this.m_RegRemove, this.m_MergeConfig.dynamicAdList, (bool success, string str)=>{
                this.Invoke(new Action(()=>{
                    txtExtractPreview.Text = success ? str : string.Empty;
                }));
            });
        }


        /// <summary>
        /// 载入默认原始html
        /// </summary>
        private void LoadDefaultOriginHtml() {
            if (Directory.Exists(m_Book.htmlDirectory)) {
                if (this.comContent.SelectedItem is Content content) {
                    string html = GetContentHtml(content);
                    txtOriginHtml.Text = html;
                }
            }
        }

        /// <summary>
        /// 合并章节
        /// </summary>
        /// <param name="author"></param>
        /// <param name="introduction"></param>
        /// <param name="updateMessage"></param>
        private void MerageText(string author, string introduction, Action<string> updateMessage) {
            if (string.IsNullOrEmpty(m_Book.name)) {
                MessageBox.Show("请先输入书名", "出错了", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } else {
                FileStream fileStream = new FileStream(OutputFilePath, FileMode.Create);
                WriteString(fileStream, string.Format("《{0}》", m_Book.name));
                WriteString(fileStream, "\r\n");
                WriteString(fileStream, "作者：" + (string.IsNullOrEmpty(author) ? "无" : author));
                WriteString(fileStream, "\r\n");
                WriteString(fileStream, "简介：");
                WriteString(fileStream, "\r\n");
                WriteString(fileStream, (string.IsNullOrEmpty(introduction) ? "无" : introduction));
                //简介之后接两个空格
                WriteString(fileStream, "\r\n");
                WriteString(fileStream, "\r\n");

                string msg;
                List<Content> errorList = new List<Content>();
                for (int i = 0; i < m_Book.contentList.Count; i++) {
                    Content content = m_Book.contentList[i];
                    string filePath = Path.Combine(m_Book.htmlDirectory, content.GetFileName());

                    if (!m_Book.ignoreContentTitle) {//如果不忽略章节标题才需要输出章节标题
                        WriteString(fileStream, content.title);
                        WriteString(fileStream, "\r\n");
                    }
                    if (!File.Exists(filePath)) {
                        errorList.Add(content);
                        WriteString(fileStream, "这个章节未下载，请原网址查看：" + content.url);
                    } else {
                        string html = GetContentHtml(content);
                        if (!ContentServer.ExtractContent(this.m_Regex, html, m_GroupId, this.m_RegRemove, this.m_MergeConfig.dynamicAdList, out string contentText)) {
                            errorList.Add(content);
                            WriteString(fileStream, "提取章节内容失败，请原网址查看：" + content.url);
                        } else {
                            WriteString(fileStream, contentText);//写入章节内容
                        }
                    }
                    if (!m_Book.ignoreContentTitle) {//如果不忽略章节标题才需要输出章节末尾的两个空行
                        WriteString(fileStream, "\r\n");
                        WriteString(fileStream, "\r\n");
                    }

                    msg = string.Format("正在合并章节：{0}/{1} {2}", i + 1, m_Book.contentList.Count, content.title);
                    Console.WriteLine(msg);
                    updateMessage?.Invoke(msg);
                }
                fileStream.Flush();
                fileStream.Close();

                if (errorList.Count < 1) {
                    msg = "合并完成";
                } else {
                    Content content = errorList[0];
                    int index = m_Book.contentList.IndexOf(content);
                    msg = $"合并完成 - 但是存在部分失败，失败的章节个数为：{errorList.Count}，\r\n首个失败索引： index=={index}\r\n标题：{content.title}";
                }

                Console.WriteLine(msg);
                updateMessage?.Invoke(msg);
                MessageBox.Show(msg, "完成", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        /// <summary>
        /// 获取章节的Html
        /// </summary>
        /// <param name="content"></param>
        /// <returns></returns>
        private string GetContentHtml(Content content) {
            string result = "";
            string filePath = Path.Combine(m_Book.htmlDirectory, content.GetFileName());
            if (!File.Exists(filePath)) {
                result = "本章并未下载下来";
            }else{
                byte[] buffer = File.ReadAllBytes(filePath);
                if (buffer != null) {
                    if (buffer.Length > 0) {
                        result = Encoding.Default.GetString(buffer);
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 检查是不是乱码
        /// </summary>
        /// <param name="txt"></param>
        /// <returns></returns>
        public bool IsLuan(string txt) {
            byte [] bytes = Encoding.UTF8.GetBytes(txt);
            //239 191 189
            for (var i = 0; i < bytes.Length; i++) {
                if (i < bytes.Length - 3) {
                    if (bytes[i] == 239 && bytes[i + 1] == 191 && bytes[i + 2] == 189) {
                        return true;
                    } else if (bytes[i] == 233 && bytes[i + 1] == 148 && bytes[i + 2] == 152) {
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 写入字符串
        /// </summary>
        /// <param name="fileStream"></param>
        /// <param name="str"></param>
        private void WriteString(FileStream fileStream, string str) {
            byte[] buffer = Encoding.UTF8.GetBytes(str);
            fileStream.Write(buffer, 0, buffer.Length);
        }

        /// <summary>
        /// 创建正则表达式匹配对象
        /// </summary>
        private void CreateMatch() {
            try {
                m_GroupId = Convert.ToInt32(txtRegContentGroupId.Text);
                
                m_Regex = new Regex(txtRegContent.Text, RegexOptions.IgnoreCase);
                
                if (!string.IsNullOrEmpty(txtRegRemove.Text)) {
                    m_RegRemove = new Regex(txtRegRemove.Text, RegexOptions.IgnoreCase);
                }
            } catch (Exception e) {
                MessageBox.Show(e.Message, "出错了", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 载入配置
        /// </summary>
        private void LoadConfig() {
            LoadMergeConfig();//载入合并配置
        }
        /// <summary>
        /// 更新配置
        /// </summary>
        private void UpdateConfig() {
            m_Book.author = txtAuthor.Text;
            m_Book.introduction = txtIntroduction.Text;
            m_Book.ignoreContentTitle = chkIgnoreContentTitle.Checked;
            UpdateMergeConfig();
        }


        /// <summary>
        /// 载入合并配置
        /// </summary>
        private void LoadMergeConfig() {
            string hostName = HtmlUtil.GetHostName(m_Book.url);
            m_MergeConfig = m_MergeConfigService.GetMergeConfig(hostName);
            txtRegContent.Text = m_MergeConfig.regContent;
            txtRegContentGroupId.Text = "" + m_MergeConfig.regContentGroupId;
            txtRegRemove.Text = m_MergeConfig.regRemove;
        }

        /// <summary>
        /// 更新合并配置
        /// </summary>
        private void UpdateMergeConfig() {
            m_MergeConfig.hostName = HtmlUtil.GetHostName(m_Book.url);
            m_MergeConfig.regContent = txtRegContent.Text;
            m_MergeConfig.regContentGroupId = Convert.ToInt32(txtRegContentGroupId.Text);
            m_MergeConfig.regRemove = txtRegRemove.Text;
            m_MergeConfigService.SaveConfig(m_MergeConfig);
        }
        

        /// <summary>
        /// 按钮 - 显示 HTML 文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnDisplayHtmlFile_Click(object sender, EventArgs e) {
            Content content = this.comContent.SelectedItem as Content;
            if(content == null) {
                MessageBox.Show("请先选择目标章节", "出错了", MessageBoxButtons.OK, MessageBoxIcon.Error);
            } else {
                string filePath = Path.Combine(m_Book.htmlDirectory, content.GetFileName());
                if (!File.Exists(filePath)) {
                    MessageBox.Show("目标文件不存在，似乎还没下载下来？？？", "出错了", MessageBoxButtons.OK, MessageBoxIcon.Error);
                } else {
                    Process process = Process.Start("Explorer", string.Format(@"/select, ""{0}""", filePath));
                    process.WaitForExit();
                }
            }
        }

        /// <summary>
        /// 按钮 - 显示输出文件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnDisplayOutputFile_Click(object sender, EventArgs e) {
            try {
                if (!File.Exists(OutputFilePath)) {
                    throw new Exception("还未合并下载的章节，请先合并！");
                }else {
                    Process process = Process.Start("Explorer", string.Format(@"/select, ""{0}""", OutputFilePath));
                    process.WaitForExit();
                }
            }catch(Exception ex) {
                MessageBox.Show(ex.Message, "出错了", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void ComContent_SelectedValueChanged(object sender, EventArgs e) {
            //默认提取预览
            this.ExtractPreview();
        }

    }
}
